package com.xmg.day11;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import sun.misc.GC;

import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class OOMDemo {
    public static void main(String[] args) {

        System.out.println("max direct memory size: "+sun.misc.VM.maxDirectMemory()/1024/1024);

        //stackOverFlow();

        //java_heap_size();

        //GC_overhead_limit_exceeded();

        //Direct_buffer_memory();

        //unable_to_create_new_native_thread();

        metaspace(args);
    }

    /**
     * 方法深度调用，方法区占满，栈内存溢出
     * Exception in thread "main" java.lang.StackOverflowError
     */
    private static void stackOverFlow(){
        stackOverFlow();
    }

    /**
     * VM参数：-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=20m
     * 堆内存溢出
     * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
     */
    private static void java_heap_size(){
        byte[] bytes = new byte[6*1024*1024];
    }


    /**
     * VM参数：-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     * 系统98%的时间都在做GC，但是每次只能回收不到2%的空间，连续多次之后抛出error
     * Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
     */
    public static void GC_overhead_limit_exceeded(){
        int i=0;
        List<String> strings = new ArrayList<>();
        try {
            while (true){
                strings.add(String.valueOf(++i).intern());
            }
        }catch (Throwable e){//此处抛出的是error，需要用Throwable捕获，不能使用Exception
            e.printStackTrace();
            System.out.println("********* i="+i);
        }
    }

    /**
     * VM参数：-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     * 直接使用本地内存的方法将本地内存撑爆，默认本地内存为物理内存的1/4
     * Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
     */
    public static void Direct_buffer_memory(){
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6*1024*1024);
    }

    /**
     * 线程数超过了系统允许的最大数，无法继续创建
     * 此异常在windows无法复现，linux非root用户默认最多创建1024个
     */
    public static void unable_to_create_new_native_thread(){
        int i = 0;
        for (int j = 0;; j++) {
            System.out.println(j);
            new Thread(()->{
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    /**
     * VM参数：-XX:Metaspace=8m -XX:MaxMetaspace=8m
     * 元空间爆出
     * java.lang.OutOfMemoryError: Metaspace
     */
    public static void metaspace(String[] args){
        int i = 0;
        try{
            while (true){
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMTest.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invokeSuper(o,args);
                    }
                });
                enhancer.create();
            }
         }catch (Throwable e){
            System.out.println("========="+i);
            e.printStackTrace();
        }
    }

    static class OOMTest{}
}
